﻿using System;
using System.Collections.Generic;
using Runtime.Services.Battle;
using Runtime.Services.Battle.Entity;
using Runtime.Services.BattleAttack;

namespace Runtime.Services.BattleSkill {

    public partial interface IDFR_BattleSkillServiceTD {

        internal sealed class Snapshot : DFR_Object, IDFR_BattleAttackSnapshot {

            private IDFR_BattleBuffProvider m_BuffProvider;

            public Snapshot(IDFR_BattleBuffProvider buffProvider) {
                m_BuffProvider = buffProvider;
            }

            public DFR_BattleAttackID ID { get; private set; }

            public DFR_BattleEntityInstanceID SourceEntityInstanceID { get; private set; }

            public DFR_BattleMapPosition LaunchMapPosition { get; private set; }

            public DFR_BattleEntityInstanceID DebuffEntityInstanceID => DFR_BattleEntityInstanceID.Empty;

            public F64 DamageHPMax { get; private set; }

            public F64 DamageHP { get; private set; }

            public F64 Damage { get; private set; }

            public F64 DamageAttack { get; private set; }

            public F64 DamageAttackBossAdditional { get; private set; }

            public F64 Attack { get; private set; }

            public F64 AttackBossAdditional { get; private set; }

            public F64 Critical { get; private set; }

            public F64 CriticalPower { get; private set; }

            public F64 BulletFlySpeed => F64.Zero;

            public string BulletHitAssetKey => null;

            public DFR_BattleAttackHit Hit { get; } = new DFR_BattleAttackHit { Type = DFR_BattleAttackType.DOT };

            public bool IsEffect => true;

            public bool IsForbiddenEliteOrBoss => false;

            public int InfluenceAmount => 1;

            public IReadOnlyDictionary<DFR_BattleEntityInstanceID, IDFR_BattleAttackTarget> KillTargetDictionary { get; } = null;

            public void Initialize(IDFR_BattleAttacker attacker, IDFR_BattleAttacker originAttacker, bool isEffect, bool isForbiddenEliteOrBoss, int influenceAmount, IDFR_BattleAttackBulletProvider bulletProvider, bool useOriginAttacker) {

                ID = new DFR_BattleAttackID { GUID = Guid.NewGuid() };

                SourceEntityInstanceID = attacker.EntityInstanceID;
                LaunchMapPosition = attacker.MapPosition;

                DamageAttack = attacker.Attack?.Value ?? F64.Zero;
                DamageAttackBossAdditional = attacker.AttackBossAdditional?.Value ?? F64.Zero;

                var damageHPBase = m_BuffProvider.DamageHPMaxBase?.Value ?? F64.Zero;
                var damageHPFactor = m_BuffProvider.DamageHPMaxFactor?.Value ?? F64.One;
                var damageHPAdditional = m_BuffProvider.DamageHPMaxAdditional?.Value ?? F64.Zero;

                var damageCurrentHPBase = m_BuffProvider.DamageHPBase?.Value ?? F64.Zero;
                var damageCurrentHPFactor = m_BuffProvider.DamageHPFactor?.Value ?? F64.One;
                var damageCurrentHPAdditional = m_BuffProvider.DamageHPAdditional?.Value ?? F64.Zero;

                var damageBase = m_BuffProvider.DamageBase?.Value ?? F64.Zero;
                var damageFactor = m_BuffProvider.DamageFactor?.Value ?? F64.One;
                var damageAdditional = m_BuffProvider.DamageAdditional?.Value ?? F64.Zero;

                var attackBase = m_BuffProvider.AttackBase?.Value ?? F64.Zero;
                var attackFactor = m_BuffProvider.AttackFactor?.Value ?? F64.One;
                var attackAdditional = m_BuffProvider.AttackAdditional?.Value ?? F64.Zero;

                var attackBossAdditionalBase = m_BuffProvider.AttackBossAdditionalBase?.Value ?? F64.Zero;
                var attackBossAdditionalFactor = m_BuffProvider.AttackBossAdditionalFactor?.Value ?? F64.One;
                var attackBossAdditionalAdditional = m_BuffProvider.AttackBossAdditionalAdditional?.Value ?? F64.Zero;

                var criticalBase = m_BuffProvider.CriticalBase?.Value ?? F64.Zero;
                var criticalFactor = m_BuffProvider.CriticalFactor?.Value ?? F64.One;
                var criticalAdditional = m_BuffProvider.CriticalAdditional?.Value ?? F64.Zero;

                var criticalPowerBase = m_BuffProvider.CriticalPowerBase?.Value ?? F64.Zero;
                var criticalPowerFactor = m_BuffProvider.CriticalPowerFactor?.Value ?? F64.One;
                var criticalPowerAdditional = m_BuffProvider.CriticalPowerAdditional?.Value ?? F64.Zero;

                DamageHPMax = damageHPBase * damageHPFactor + damageHPAdditional;
                DamageHP = damageCurrentHPBase * damageCurrentHPFactor + damageCurrentHPAdditional;
                Damage = damageBase * damageFactor + damageAdditional;
                Attack = attackBase * attackFactor + attackAdditional;
                AttackBossAdditional = attackBossAdditionalBase * attackBossAdditionalFactor + attackBossAdditionalAdditional;
                Critical = criticalBase * criticalFactor + criticalAdditional;
                CriticalPower = criticalPowerBase * criticalPowerFactor + criticalPowerAdditional;
            }

            public void Lightweight() {
                m_BuffProvider = null;
            }

            protected override void Dispose() {
                Lightweight();
            }
        }
    }
}
